#ifndef USERSKELETON_H
#define USERSKELETON_H

#include <QMap>
#include <QGenericMatrix>
#include <QVector3D>
#include <QPointF>

/**
  * @brief Represents a single frame of input from the Kinect via the OpenNI framework, with all metadata retrieved from
  * OpenNI including:
  *  * Joint positions
  *  * Joint projections (x, y position of the joint on the 2D image overlay)
  *  * Joint position confidences
  *  * Joint orientations
  *  * Joint orientation confidences
  */
class UserSkeleton {
public:
    // Values are extracted from XnSkeletonJoint in the OpenNI framework
    // Not all will be used, but just in case.
    enum UserJoint {
        Head = 1,
        Neck = 2,
        Torso = 3,
        Waist = 4,
        LeftCollar = 5,
        LeftShoulder = 6,
        LeftElbow = 7,
        LeftWrist = 8,
        LeftHand = 9,
        LeftFingerTip = 10,
        RightCollar= 11,
        RightShoulder = 12,
        RightElbow = 13,
        RightWrist = 14,
        RightHand = 15,
        RightFingertip = 16,
        LeftHip = 17,
        LeftKnee = 18,
        LeftAnkle = 19,
        LeftFoot = 20,
        RightHip = 21,
        RightKnee = 22,
        RightAnkle = 23,
        RightFoot = 24
    };
public:
    /**
      * Creates an empty UserSkeleton.
      */
    UserSkeleton();
    /**
      * Destroys and deallocates a UserSkeleton.
      */
    ~UserSkeleton();

    /**
      * Checks whether the skeleton has the position of a joint.
      *
      * @param userJoint
      */
    bool hasUserPosition(int userJoint) const;
    /**
      * Gets the position of the indicated joint.
      *
      * @param userJoint
      */
    QVector3D userPosition(int userJoint) const;
    /**
      * Gets the projection of the indicated joint.
      *
      * @param userJoint
      */
    QPointF userProjection(int userJoint) const;
    /**
      * Sets the position and projectiong of the indicated joint.
      *
      * @param userJoint
      * @param position
      * @param projection
      */
    void setUserPosition(int userJoint, QVector3D position, QPointF projection);

    /**
      * Checks whether this pose has an orientation for the indicated joint.
      *
      * @param userJoint
      */
    bool hasUserOrientation(int userJoint) const;
    /**
      * Gets the orientation for the indicated joint.
      *
      * @param userJoint
      */
    QMatrix3x3 userOrientation(int userJoint) const;
    /**
      * Sets the orientation for the indicated joint.
      *
      * @param userJoint
      * @param orientation
      */
    void setUserOrientation(int userJoint, QMatrix3x3 orientation);

    /**
      * Gets the confidence OpenNI had in the position of the indicated joint as a float between 0 (no confidence) and 1
      * (perfectly confident).
      *
      * @param userJoint
      */
    float userPositionConfidence(int userJoint) const;
    /**
      * Sets the confidence of the position of the indicated joint.
      *
      * @param userJoint
      * @param conf
      */
    void setUserPositionConfidence(int userJoint, float conf);

    /**
      * Gets the confidence OpenNI had in the orientation of the indicated joint as a float between 0 (no confidence) and 1
      * (perfectly confident).
      *
      * @param userJoint
      */
    float userOrientationConfidence(int userJoint) const;
    /**
      * Sets the confidence of the orientation of the indicated joint.
      *
      * @param userJoint
      * @param conf
      */
    void setUserOrientationConfidence(int userJoint, float conf);

    /**
      * Gets a vector containing all possible joints a UserSkeleton can have.
      */
    static QVector<UserJoint> allJoints();
private:
    QMap<int, QVector3D> positions;
    QMap<int, QPointF> projections;
    QMap<int, float> positionConfidence;
    QMap<int, QMatrix3x3> orientations;
    QMap<int, float> orientationConfidence;

    static QVector<UserJoint> staticJoints;
};

#endif // USERSKELETON_H
